home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / src890906.arc / SLIP.C < prev    next >
C/C++ Source or Header  |  1989-08-19  |  5KB  |  244 lines

  1. /* Send and receive IP datagrams on serial lines. Compatible with SLIP
  2.  * under Berkeley Unix.
  3.  */
  4. #include <stdio.h>
  5. #include "global.h"
  6. #include "mbuf.h"
  7. #include "iface.h"
  8. #include "ax25.h"
  9. #include "slip.h"
  10. #include "asy.h"
  11. #include "trace.h"
  12.  
  13. static void asy_start __ARGS((int16 dev));
  14. static struct mbuf *slip_decode __ARGS((int16 dev,char c));
  15. static struct mbuf *slip_encode __ARGS((struct mbuf *bp));
  16. static int slipq __ARGS((int16 dev,struct mbuf *data));
  17.  
  18. /* Slip level control structure */
  19. struct slip Slip[ASY_MAX];
  20.  
  21. /* Send routine for point-to-point slip
  22.  * This is a trivial function since there is no slip link-level header
  23.  */
  24. int
  25. slip_send(data,iface,gateway,prec,del,tput,rel)
  26. struct mbuf *data;    /* Buffer to send */
  27. struct iface *iface;    /* Pointer to interface control block */
  28. int32 gateway;        /* Ignored (SLIP is point-to-point) */
  29. int prec;
  30. int del;
  31. int tput;
  32. int rel;
  33. {
  34.     if(iface == NULLIF){
  35.         free_p(data);
  36.         return -1;
  37.     }
  38.     return (*iface->raw)(iface,data);
  39. }
  40. /* Send a raw slip frame -- also trivial */
  41. int
  42. slip_raw(iface,data)
  43. struct iface *iface;
  44. struct mbuf *data;
  45. {
  46.     dump(iface,IF_TRACE_OUT,Slip[iface->dev].type,data);
  47.     /* Queue a frame on the slip output queue and start transmitter */
  48.     return slipq(iface->dev,data);
  49. }
  50. /* Encode a raw packet in slip framing, put on link output queue, and kick
  51.  * transmitter
  52.  */
  53. static int
  54. slipq(dev,data)
  55. int16 dev;        /* Serial line number */
  56. struct mbuf *data;    /* Buffer to be sent */
  57. {
  58.     register struct slip *sp;
  59.     struct mbuf *bp;
  60.  
  61.     if((bp = slip_encode(data)) == NULLBUF)
  62.         return -1;    
  63.  
  64.     sp = &Slip[dev];
  65.     enqueue(&sp->sndq,bp);
  66.     sp->sndcnt++;
  67.     asy_start(dev);
  68.     return 0;
  69. }
  70. /* Start output, if possible, on asynch device dev */
  71. static void
  72. asy_start(dev)
  73. int16 dev;
  74. {
  75.     register struct slip *sp;
  76.     char i_state;
  77.  
  78.     i_state = dirps();
  79.     if(!stxrdy(dev)){
  80.         restore(i_state);
  81.         return;        /* Transmitter not ready */
  82.     }
  83.     sp = &Slip[dev];
  84.     if(sp->tbp != NULLBUF){
  85.         /* transmission just completed */
  86.         free_p(sp->tbp);
  87.         sp->tbp = NULLBUF;
  88.     }
  89.     if(sp->sndq == NULLBUF){
  90.         restore(i_state);
  91.         return;    /* No work */
  92.     }
  93.     sp->tbp = dequeue(&sp->sndq);
  94.     sp->sndcnt--;
  95.     asy_output(dev,sp->tbp->data,sp->tbp->cnt);
  96.     restore(i_state);
  97. }
  98. /* Encode a packet in SLIP format */
  99. static
  100. struct mbuf *
  101. slip_encode(bp)
  102. struct mbuf *bp;
  103. {
  104.     struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  105.     register char *cp;
  106.     char c;
  107.  
  108.     /* Allocate output mbuf that's twice as long as the packet.
  109.      * This is a worst-case guess (consider a packet full of FR_ENDs!)
  110.      */
  111.     lbp = alloc_mbuf(2*len_mbuf(bp) + 2);
  112.     if(lbp == NULLBUF){
  113.         /* No space; drop */
  114.         free_p(bp);
  115.         return NULLBUF;
  116.     }
  117.     cp = lbp->data;
  118.  
  119.     /* Flush out any line garbage */
  120.     *cp++ = FR_END;
  121.  
  122.     /* Copy input to output, escaping special characters */
  123.     while(pullup(&bp,&c,1) == 1){
  124.         switch(uchar(c)){
  125.         case FR_ESC:
  126.             *cp++ = FR_ESC;
  127.             *cp++ = T_FR_ESC;
  128.             break;
  129.         case FR_END:
  130.             *cp++ = FR_ESC;
  131.             *cp++ = T_FR_END;
  132.             break;
  133.         default:
  134.             *cp++ = c;
  135.         }
  136.     }
  137.     *cp++ = FR_END;
  138.     lbp->cnt = cp - lbp->data;
  139.     return lbp;
  140. }
  141. /* Process incoming bytes in SLIP format
  142.  * When a buffer is complete, return it; otherwise NULLBUF
  143.  */
  144. static
  145. struct mbuf *
  146. slip_decode(dev,c)
  147. int16 dev;    /* Slip unit number */
  148. char c;        /* Incoming character */
  149. {
  150.     struct mbuf *bp;
  151.     register struct slip *sp;
  152.  
  153.     sp = &Slip[dev];
  154.     switch(uchar(c)){
  155.     case FR_END:
  156.         bp = sp->rbp;
  157.         sp->rbp = NULLBUF;
  158.         sp->rcnt = 0;
  159.         return bp;    /* Will be NULLBUF if empty frame */
  160.     case FR_ESC:
  161.         sp->escaped = 1;
  162.         return NULLBUF;
  163.     }
  164.     if(sp->escaped){
  165.         /* Translate 2-char escape sequence back to original char */
  166.         sp->escaped = 0;
  167.         switch(uchar(c)){
  168.         case T_FR_ESC:
  169.             c = FR_ESC;
  170.             break;
  171.         case T_FR_END:
  172.             c = FR_END;
  173.             break;
  174.         default:
  175.             sp->errors++;
  176.             break;
  177.         }
  178.     }
  179.     /* We reach here with a character for the buffer;
  180.      * make sure there's space for it
  181.      */
  182.     if(sp->rbp == NULLBUF){
  183.         /* Allocate first mbuf for new packet */
  184.         if((sp->rbp1 = sp->rbp = alloc_mbuf(SLIP_ALLOC)) == NULLBUF)
  185.             return NULLBUF; /* No memory, drop */
  186.         sp->rcp = sp->rbp->data;
  187.     } else if(sp->rbp1->cnt == SLIP_ALLOC){
  188.         /* Current mbuf is full; link in another */
  189.         if((sp->rbp1->next = alloc_mbuf(SLIP_ALLOC)) == NULLBUF){
  190.             /* No memory, drop whole thing */
  191.             free_p(sp->rbp);
  192.             sp->rbp = NULLBUF;
  193.             sp->rcnt = 0;
  194.             return NULLBUF;
  195.         }
  196.         sp->rbp1 = sp->rbp1->next;
  197.         sp->rcp = sp->rbp1->data;
  198.     }
  199.     /* Store the character, increment fragment and total
  200.      * byte counts
  201.      */
  202.     *sp->rcp++ = c;
  203.     sp->rbp1->cnt++;
  204.     sp->rcnt++;
  205.     return NULLBUF;
  206. }
  207. /* Process SLIP line input */
  208. void
  209. asy_rx(dev,p1,p2)
  210. int dev;
  211. void *p1;
  212. void *p2;
  213. {
  214.     char c;
  215.     struct mbuf *bp,*nbp;
  216.     struct phdr *phdr;
  217.     struct slip *sp;
  218.  
  219.     sp = &Slip[dev];
  220.  
  221.     for(;;){
  222.         c = get_asy(dev);
  223.         if((bp = slip_decode(dev,c)) == NULLBUF)
  224.             continue;    /* More to come */
  225.  
  226.         if((nbp = pushdown(bp,sizeof(struct phdr))) == NULLBUF){
  227.             free_p(bp);
  228.             continue;
  229.         }
  230.         phdr = (struct phdr *)nbp->data;
  231.         phdr->iface = sp->iface;
  232.         phdr->type = sp->type;
  233.         enqueue(&Hopper,nbp);
  234.     }
  235. }
  236. void
  237. asytxdone(dev)
  238. int16 dev;
  239. {
  240.     /* Kick the transmitter if it's idle */
  241.     if(stxrdy(dev))
  242.         asy_start(dev);
  243. }
  244.